package com.logic.config.netty.web.handler;

import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.logic.config.web.annotation.ActionController;
import com.logic.config.web.annotation.ActionMethod;
import com.logic.config.netty.web.model.message.ActionBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@ActionController(1)
@Slf4j
@Configuration
public class ActionRequestHandleMapping {
    private final Map<String, Object> cache = new ConcurrentHashMap<>();

    @PostConstruct
    private void init() {
        Set<Class<?>> classes = ClassScanner.scanPackageByAnnotation("com.game", ActionController.class);
        Map<? extends Class<?>, Method[]> collect = classes.stream()
                .collect(Collectors.toMap(
                        cls -> cls,
                        cls -> ReflectUtil.getMethods(cls, method -> method.isAnnotationPresent(ActionMethod.class))
                ));
        cache.put("action", collect);
    }

    @SuppressWarnings("unchecked")
    public Object obtainActionRes(ActionBody actionBody) {
        Integer mainRoute = actionBody.getMainRoute();
        Integer subRoute = actionBody.getSubRoute();
        Map<? extends Class<?>, Method[]> action = (Map<? extends Class<?>, Method[]>) cache.get("action");
        for (Map.Entry<? extends Class<?>, Method[]> entry : action.entrySet()) {
            Class<?> key = entry.getKey();
            ActionController annotation = key.getAnnotation(ActionController.class);
            int value = annotation.value();
            if (value == mainRoute) {
                Method[] value1 = entry.getValue();
                for (Method method : value1) {
                    ActionMethod annotation1 = method.getAnnotation(ActionMethod.class);
                    int value2 = annotation1.value();
                    if (value2 == subRoute) {
                        Class<?>[] parameterType = method.getParameterTypes();
                        // 方法参数列表
                        Object[] args = new Object[parameterType.length];
                        for (int i = 0; i < parameterType.length; i++) {
                            Class<?> aClass = parameterType[i];
                            args[0] = actionBody.getToken();
                            Object bean1 = JSONUtil.toBean(actionBody.getData(), aClass);
                            args[i] = bean1;
                        }
                        return ReflectUtil.invoke(SpringUtil.getBean(key), method, args);
                    }
                }
            }
        }
        log.error("未找到对应的Action{}-Method-{}", mainRoute, subRoute);
        return null;
    }
}
